package com.xx.secret.core;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xx.secret.annotation.Ignore;
import com.xx.secret.annotation.Secret;
import com.xx.secret.util.AppUtil;
import com.xx.secret.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ：wangcheng
 * @date 2023/11/15
 **/
@Aspect
@Component
@Slf4j
public class SecretHandler {

    private final DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();

    @Pointcut("@annotation(secret) || @within(secret)")
    public void annotationPointCut(Secret secret) {
    }

    @Around(value = "annotationPointCut(secret)")
    public Object secretHandler(ProceedingJoinPoint pjp, Secret secret) throws Throwable {
        IOpenVerify loanVerifyClazz = null;
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        Secret annotation = method.getAnnotation(Secret.class);
        if (annotation!=null) {
            secret = annotation;
        }
        String openLoanName = secret.loanEnum().getLoanName();
        try {
            loanVerifyClazz = OpenContextProvider.getLoanVerifyClazz(secret.loanEnum().getApiName());
            JSONObject param = AppUtil.getParam();
            Ignore ignore = secret.ignoreField();
            String originalParamLog = JsonUtil.removeKey(JSON.toJSONString(param), ignore.originalParamKey());
            log.info("secret handler 获取原请求参数: {} loanName: {} ",originalParamLog,openLoanName);
            //验签
            loanVerifyClazz.verify(param);
            //解密 无需解密返回原参数
            String decryptParam = loanVerifyClazz.decryptParam(param);
            String decryptParamLog = JsonUtil.removeKey(decryptParam, ignore.decryptParamKey());
            log.info("secret handler 获取解密参数: {} loanName: {} ",decryptParamLog,openLoanName);
            Object proceed = pjp.proceed(getArgs(decryptParam, pjp, secret.parseArgsFlag()));
            log.info("secret handler 明文返回数据: {} loanName: {} " ,JSON.toJSONString(proceed),openLoanName);
            Object encryptResponse = loanVerifyClazz.encryptResponse(proceed);
            log.info("secret handler 加密返回数据: {} loanName: {} ",JSON.toJSONString(encryptResponse),openLoanName);
            return encryptResponse;
        }catch (Exception e) {
            //异常处理
            Object errorResp = loanVerifyClazz.exceptionResponse(e);
            log.error("secret handler 处理加解密异常: {} loanName: {} 异常返回: {} ",e.getMessage(),openLoanName,JSON.toJSONString(errorResp),e);
            return errorResp;
        }

    }

    private Object[] getArgs(String decryptParam,ProceedingJoinPoint pjp,boolean parseArgsFlag) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        String[] parameterNames = signature.getParameterNames();
        Class[] parameterTypes = signature.getParameterTypes();
        if (parseArgsFlag) {
            JSONObject argObj = JSON.parseObject(decryptParam);
            List<Object> list = new ArrayList<>();
            for (int i = 0; i < parameterNames.length; i++) {
                list.add(argObj.getObject(parameterNames[i],parameterTypes[i]));
            }
            return list.toArray();
        }else {
            Object object = JSONObject.parseObject(decryptParam, parameterTypes[0]);
            return new Object[]{object};
        }

    }

}
